#include "gt1151.h"

#define GT1151_COMMAND			0x8040		//控制命令寄存器
#define GT1151_CONFIG			0x8050		//配置寄存器起始
#define GT1151_PRODUCT_ID		0x8140		//产品ID
#define GT1151Q_GSTID_REG		0x814E		//GT1151Q当前检测到的触摸情况
#define GT1151Q_TP1_REG			0x814F		//第1个触摸点数据地址
#define GT1151Q_TP2_REG			0x8157		//第2个触摸点数据地址
#define GT1151Q_TP3_REG			0x815F		//第3个触摸点数据地址
#define GT1151Q_TP4_REG			0x8167		//第4个触摸点数据地址
#define GT1151Q_TP5_REG			0x816F		//第5个触摸点数据地址
#define GT1151Q_TP6_REG			0x8177		//第6个触摸点数据地址
#define GT1151Q_TP7_REG			0x817F		//第7个触摸点数据地址
#define GT1151Q_TP8_REG			0x8187		//第8个触摸点数据地址
#define GT1151Q_TP9_REG			0x818F		//第9个触摸点数据地址
#define GT1151Q_TP10_REG		0x8197		//第10个触摸点数据地址

#define GT1151_HW_CONFIG_LEN	239
#define GTP_MAX_TOUCH			5

struct gt1151_dev{
	struct input_dev	*inputdev;
	struct i2c_client	*client;
	int					rst_pin;				/* 复位引脚 */
	int					intr_pin;				/* 中断引脚 */
	uint32_t			x_range;
	uint32_t			y_range;
	uint32_t			id;
	uint8_t				last_touch_state[GTP_MAX_TOUCH];
	uint8_t				write_buffer[512];
	uint8_t				gt1151_config[GT1151_HW_CONFIG_LEN];
};

static const uint16_t tp_reg[GTP_MAX_TOUCH] = {
#if GTP_MAX_TOUCH >= 1
	GT1151Q_TP1_REG,
#endif
#if GTP_MAX_TOUCH >= 2
	GT1151Q_TP2_REG,
#endif
#if GTP_MAX_TOUCH >= 3
	GT1151Q_TP3_REG,
#endif
#if GTP_MAX_TOUCH >= 4
	GT1151Q_TP4_REG,
#endif
#if GTP_MAX_TOUCH >= 5
	GT1151Q_TP5_REG,
#endif
#if GTP_MAX_TOUCH >= 6
	GT1151Q_TP6_REG,
#endif
#if GTP_MAX_TOUCH >= 7
	GT1151Q_TP7_REG,
#endif
#if GTP_MAX_TOUCH >= 8
	GT1151Q_TP8_REG,
#endif
#if GTP_MAX_TOUCH >= 9
	GT1151Q_TP9_REG,
#endif
#if GTP_MAX_TOUCH >= 10
	GT1151Q_TP10_REG,
#endif
};

static int gt1151_read(struct gt1151_dev *gt1151, uint16_t reg, uint8_t *data, uint16_t lenght)
{
	uint8_t addr[2];
	struct i2c_msg msg[2];

	addr[0] = (uint8_t)((reg >> 8) & 0xFF);
	addr[1] = (uint8_t)(reg & 0xFF);

	//从机地址
	msg[0].addr = gt1151->client->addr;
	//表示写
	msg[0].flags = 0;
	//buf是一个指针,指向了要发送的数据
	msg[0].buf = addr;
	//msg[0].buf的数据长度
	msg[0].len = 2;

	msg[1].addr = gt1151->client->addr;
	//表示读
	msg[1].flags = I2C_M_RD;
	msg[1].buf = data;
	msg[1].len = lenght;
	if(i2c_transfer(gt1151->client->adapter, msg, 2)  == 2)
		return 0;
	else 
		return -EIO;
}

static int gt1151_write(struct gt1151_dev *gt1151, uint16_t reg, uint8_t *data, uint16_t lenght)
{
	struct i2c_msg msg[1];
	
	if(lenght > sizeof(gt1151->write_buffer)-2)
		return -EIO;

	memset(gt1151->write_buffer, 0, sizeof(gt1151->write_buffer));
	//只能用一个msg发送，分多个msg时msg衔接的时候不会等待设备的ACK信号，可能会导致失败
	gt1151->write_buffer[0] = (uint8_t)((reg >> 8) & 0xFF);
	gt1151->write_buffer[1] = (uint8_t)(reg & 0xFF);
	memcpy(&gt1151->write_buffer[2], data, lenght);

	//从机地址
	msg[0].addr = gt1151->client->addr;
	//表示写
	msg[0].flags = 0;
	//buf是一个指针,指向了要发送的数据
	msg[0].buf = gt1151->write_buffer;
	//msg[0].buf的数据长度
	msg[0].len = 2 + lenght;
	if(i2c_transfer(gt1151->client->adapter, msg, 1)  == 1)
		return 0;
	else
		return -EIO;
}

static irqreturn_t gt1151_irq_thread(int irq, void *arg)
{
	uint8_t i;
	uint8_t clr_intr;
	uint8_t touch_number;
	uint8_t phy_id;
	uint16_t x_coordinate;
	uint16_t y_coordinate;
	int32_t result;
	uint8_t buffer[5];
	uint8_t now_touch_state[GTP_MAX_TOUCH];
	struct gt1151_dev *gt1151 = (struct gt1151_dev*)arg;

	//读取触摸数据
	result = gt1151_read(gt1151, GT1151Q_GSTID_REG, buffer, 1);
	if(result != 0) {
		printk("read reg failed\r\n");
		return IRQ_HANDLED;
	}

	//获取触摸点数
	touch_number = buffer[0] & 0x0F;

	//复位当前触摸状态
	memset(now_touch_state, 0, sizeof(now_touch_state));
	//依次处理触摸点
	for(i=0; (i<touch_number) && (i<GTP_MAX_TOUCH); i++) 
	{
		//读取一个触摸点
		result = gt1151_read(gt1151, tp_reg[i], buffer, 5);
		if(result != 0) {
			printk("read reg failed\r\n");
			return IRQ_HANDLED;
		}

		//获取触摸点ID
		phy_id = buffer[0] & 0x0F;
		//ID不合法
		if(phy_id >= GTP_MAX_TOUCH) {
			continue;
		}

		//获取触摸坐标
		x_coordinate = buffer[1] | (buffer[2] << 8);
		y_coordinate = buffer[3] | (buffer[4] << 8);
		//记录当前触摸点的状态
		now_touch_state[phy_id] = 1;

		//通过第phy_id个slot上报ABS_MT_SLOT事件，表示即将上报第phy_id的触摸信息
		input_mt_slot(gt1151->inputdev, phy_id);
		//上报触摸状态
		input_mt_report_slot_state(gt1151->inputdev, MT_TOOL_FINGER, true);
		//上报触摸坐标
		input_report_abs(gt1151->inputdev, ABS_MT_POSITION_X, x_coordinate);
		input_report_abs(gt1151->inputdev, ABS_MT_POSITION_Y, y_coordinate);
	}

	//处理松开的点
	for(i=0; i<GTP_MAX_TOUCH; i++) {
		//上一次处于按下状态而此次处于松开状态
		if((!now_touch_state[i]) && (gt1151->last_touch_state[i])) 
		{
			//触摸ID
			phy_id = i;

			//上报触摸信息
			input_mt_slot(gt1151->inputdev, phy_id);
			input_mt_report_slot_state(gt1151->inputdev, MT_TOOL_FINGER, false);
		}
	}

	//记录此次触摸状态
	memcpy(gt1151->last_touch_state, now_touch_state, sizeof(gt1151->last_touch_state));

	//进行单点触摸模拟，并上报触摸点数
	input_mt_report_pointer_emulation(gt1151->inputdev, true);
	//上报完成，进行事件同步
	input_sync(gt1151->inputdev);

	//清除触摸屏中断标志
	clr_intr = 0x00;
	gt1151_write(gt1151, GT1151Q_GSTID_REG, &clr_intr, 1);

	//返回IRQ_HANDLED，表示中断被成功处理
	return IRQ_HANDLED;
}

static int gt1151_reset(struct gt1151_dev *gt1151)
{
	uint8_t data;

	if(gt1151->client->addr != 0x14)
	{
		printk("address bad\r\n");
		return -EINVAL;
	}

	//进行软件复位
	data = 0x02;
	gt1151_write(gt1151, 0X8040, &data, 1);
	mdelay(100);
	data = 0x0;
	gt1151_write(gt1151, 0X8040, &data, 1);
	mdelay(100);

	return 0;
}

static int32_t gt1151_config(struct gt1151_dev *gt1151)
{
	uint16_t checksum;
	int i;
	int result;
	uint8_t buffer[5];
	uint8_t *config = gt1151->gt1151_config;
	uint16_t cfg_len = GT1151_HW_CONFIG_LEN;

	//读取产品ID
	gt1151_read(gt1151, GT1151_PRODUCT_ID, buffer, 4);
	buffer[4] = 0x00;
	printk("gt1151 ID: %s\r\n", (char*)buffer);

	//加载配置数据
	result = gt1151_read(gt1151, GT1151_CONFIG, config, cfg_len);
	if(result != 0)
	{
		printk("load config failed\r\n");
		return result;
	}

	//配置触摸屏尺寸
	config[1] = gt1151->x_range & 0xFF;
	config[2] = gt1151->x_range >> 8;
	config[3] = gt1151->y_range & 0xFF;
	config[4] = gt1151->y_range >> 8;

	//计算和校验
	checksum = 0;
	for (i=0; i<cfg_len-3; i+=2) 
		checksum += ((uint16_t)config[i] << 8) + config[i+1];
	checksum = 0 - checksum;
	config[cfg_len-3] = (uint8_t)(checksum >> 8);
	config[cfg_len-2] = (uint8_t)(checksum & 0xFF);
	config[cfg_len-1] = 0x01;

	//更新配置数据
	return gt1151_write(gt1151, GT1151_CONFIG, config, cfg_len);
}

static int gt1151_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int result;
	uint32_t irq_flags;
	struct gt1151_dev *gt1151;

	printk("%s\r\n", __FUNCTION__);

	//分配gt1151设备
	gt1151 = devm_kmalloc(&client->dev, sizeof(struct gt1151_dev), GFP_KERNEL);
	if(!gt1151)
	{
		printk("malloc mem failed\r\n");
		return -ENOMEM;
	}
	memset(gt1151, 0, sizeof(struct gt1151_dev));

	//在client中设置驱动私有数据
	client->dev.driver_data = gt1151;

	gt1151->client = client;
	//尺寸默认800*480
	gt1151->x_range = 800;
	gt1151->y_range = 480;
	
	//获取GPIO号
	gt1151->rst_pin = of_get_named_gpio(client->dev.of_node, "reset-gpios", 0);
	if(gt1151->rst_pin < 0)
	{
		printk("get reset gpio failed\r\n");
		return gt1151->rst_pin;
	}
	gt1151->intr_pin = of_get_named_gpio(client->dev.of_node, "interrupt-gpios", 0);
	if(gt1151->intr_pin < 0)
	{
		printk("get irq gpio failed\r\n");
		return gt1151->intr_pin;
	}

	//申请GPIO
	result = devm_gpio_request(&client->dev, gt1151->rst_pin, "gt1151-reset");
	if(result != 0)
	{
		printk("request reset gpio failed\r\n");
		return result;
	}
	result = devm_gpio_request(&client->dev, gt1151->intr_pin, "gt1151-irq");
	if(result != 0)
	{
		printk("request irq gpio failed\r\n");
		return result;
	}

	//获取尺寸
	of_property_read_u32(client->dev.of_node, "x-size", &gt1151->x_range);
	of_property_read_u32(client->dev.of_node, "y-size", &gt1151->y_range);
	printk("size:%d*%d\r\n", gt1151->x_range, gt1151->y_range);

	//复位gt1151
	result = gt1151_reset(gt1151);
	if(result != 0)
	{
		printk("reset failed\r\n");
		return result;
	}

	//配置gt1151
	result = gt1151_config(gt1151);
	if(result != 0)
	{
		printk("config failed\r\n");
		return result;
	}

	//分配输入设备
	gt1151->inputdev = devm_input_allocate_device(&client->dev);
	if(!gt1151->inputdev)
	{
		printk("alloc input device failed\r\n");
		return -ENOMEM;
	}

	//初始化输入设备
	gt1151->inputdev->name = client->name;
	gt1151->inputdev->id.bustype = BUS_I2C;
	// //input_mt_init_slots函数的flags为INPUT_MT_DIRECT会设置此事件
	// __set_bit(EV_KEY, gt1151->inputdev->evbit);
	// //input_set_abs_params函数会设置此事件
	// __set_bit(EV_ABS, gt1151->inputdev->evbit);
	// //input_mt_init_slots函数的flags为INPUT_MT_DIRECT会设置此事件
	// __set_bit(BTN_TOUCH, gt1151->inputdev->keybit);
	input_set_abs_params(gt1151->inputdev, ABS_X, 0, gt1151->x_range, 0, 0);
	input_set_abs_params(gt1151->inputdev, ABS_Y, 0, gt1151->y_range, 0, 0);
	input_set_abs_params(gt1151->inputdev, ABS_MT_POSITION_X, 0, gt1151->x_range, 0, 0);
	input_set_abs_params(gt1151->inputdev, ABS_MT_POSITION_Y, 0, gt1151->y_range, 0, 0);
	// result = input_mt_init_slots(gt1151->inputdev, GTP_MAX_TOUCH, 0);
	//flags为INPUT_MT_DIRECT会设置EV_KEY、BTN_TOUCH事件，并讲ABS_MT_POSITION_X和ABS_MT_POSITION_Y拷贝到ABS_X和ABS_Y
	result = input_mt_init_slots(gt1151->inputdev, GTP_MAX_TOUCH, INPUT_MT_DIRECT);
	if(result != 0)
	{
		printk("mt init failed\r\n");
		return result;
	}

	//注册输入设备
	result = input_register_device(gt1151->inputdev);
	if(result != 0)
	{
		printk("input register failed\r\n");
		return result;
	}

	//设置中断引脚为输入
	gpio_direction_input(gt1151->intr_pin);
	//获取中断触发方式
	irq_flags = irq_get_trigger_type(gt1151->client->irq);
	if(irq_flags == IRQF_TRIGGER_NONE)
		irq_flags = IRQF_TRIGGER_FALLING;
	irq_flags |= IRQF_ONESHOT;
	result = devm_request_threaded_irq(&client->dev, client->irq, NULL, gt1151_irq_thread, irq_flags, client->name, gt1151);
	if(result != 0)
	{
		printk("request irq failed\r\n");
		input_unregister_device(gt1151->inputdev);
		return result;
	}

	return 0;
}

static int gt1151_remove(struct i2c_client *client)
{
	struct gt1151_dev *gt1151;

	printk("%s\r\n", __FUNCTION__);

	gt1151 = client->dev.driver_data;
	input_unregister_device(gt1151->inputdev);

	return 0;
}

static const struct i2c_device_id gt1151_id[] = {
	//采用设备树匹配，这里可以为空
	{"atk-gt1151", 0},
	{ /* Sentinel */ }
};

static const struct of_device_id gt1151_of_match[] = {
	{ .compatible = "atk-gt1151"},
	{ /* Sentinel */ }
};

static struct i2c_driver gt1151_driver = {
	.probe = gt1151_probe,
	.remove = gt1151_remove,
	.driver = {
			.owner = THIS_MODULE,
			.name = "gt1151",
			.of_match_table = gt1151_of_match, 
		},
	//I2C驱动的此项参数不能为NULL
	.id_table = gt1151_id, 
};

static int __init gt1151_init(void)
{
	int result;

	printk("%s\r\n", __FUNCTION__);

	result = i2c_add_driver(&gt1151_driver);
	if(result != 0)
	{
		printk("add gt1151 driver failed\r\n");
		return result;
	}
	return 0;
}

static void __exit gt1151_exit(void)
{
	printk("%s\r\n", __FUNCTION__);

	i2c_del_driver(&gt1151_driver);
}

module_init(gt1151_init);
module_exit(gt1151_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("lf");
MODULE_DESCRIPTION("gt1151 driver");

